/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../macro/head.h"
#include "../impl/head.h"
#include "servlet.h"

namespace xos_servlet
{
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    static servlet::ITEM_DATA xos_item_data;

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 

    servlet::servlet()
    {
        init_data();
    }

    servlet::~servlet()
    {
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // public method

    int servlet::get_xos_item_data( ITEM_DATA*& item_ptr )
    {
        int ret = 0;
        xos_item_data.set_container( mgr::container() );
        item_ptr = &xos_item_data;
        return ret;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    http::i_servlet::enumRet servlet::proc( http::i_task * pTask )
    {
        http::i_servlet::enumRet eRet = http::i_servlet::RET_DONE;
        int step = 0;
        int ret = 0;

        // 返回异步，想要进入slow线程
        if( ( m_nStep == step++ ) && ( 0 == ret ) )
        {
            eRet = http::i_servlet::RET_SLOW;
            prepare_db( pTask );
            m_nStep++;
            ret = 1;
        }

        // 在慢速线程中，返回continue,会再次进入fast线程
        if( ( m_nStep == step++ ) && ( 0 == ret ) )
        {
            eRet = http::i_servlet::RET_FAST;
            execute_db( pTask );
            m_nStep++;
            ret = 1;
        }

        // 回到fast线程，发起异步调用
        if( ( m_nStep == step++ ) && ( 0 == ret ) )
        {
            eRet = http::i_servlet::RET_CALL;
            pTask->values()->set( "servlet", "main" );
            pTask->call( "/jsp/main.xos" );
            m_nStep++;
            ret = 1;
        }

        // 回到fast线程，最后完成
        if( ( m_nStep == step++ ) && ( 0 == ret ) )
        {
            helper_proc( pTask );
            m_nStep++;
        }

        return eRet;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int servlet::prepare_db( http::i_task * pTask )
    {
        int ret = 0;

        xos_box::i_string * pStrTime = mgr::container()->box()->string();
        xos_box::i_string * pStrInfo = mgr::container()->box()->string();
        const char * lpszInfo = 0;

        xos::i_time * pTime = mgr::container()->xos()->tm();

        {
            pTime->get_time();
            pTime->get_time_name_ymdhms( pStrTime );
            mgr::container()->crt()->sprintf( pStrInfo, "this is in servlet, simulate slow job, will block 1 second, time = %s", pStrTime->get( 0, 0 ) );
            lpszInfo = pStrInfo->get( 0, 0 );
        }
        {
            LOG4( "-----------------------------------prepare db job..." );
            LOG4( "servlet info : %s", lpszInfo );
        }

        xos_stl::release_interface( pStrTime );
        xos_stl::release_interface( pStrInfo );
        xos_stl::release_interface( pTime );
        return ret;
    }

    int servlet::execute_db( http::i_task * pTask )
    {
        int ret = 0;
        {
            LOG4( "-----------------------------------begin doing slow db job..." );
            //mgr::container()->misc()->sleep( 1000 );
            LOG4( "-----------------------------------end doing slow db job" );
        }
        xos_odbc::i_connect_pool * pPool = (xos_odbc::i_connect_pool *)mgr::container()->config()->get( "xos_http_odbc_connect_pool" );
        xos_odbc::i_connect * pConnect = 0;
        xos_odbc::i_recordset * pSet = 0;
        xos_box::i_string * pStrInfo = mgr::container()->box()->string();
        xos_box::i_string * pStr = mgr::container()->box()->string();
        xos_box::i_variant * pV = mgr::container()->box()->vt();
        if( ( 0 == ret ) && !pPool )
        {
            ret = 1;
        }
        if( 0 == ret )
        {
            pConnect = pPool->get();
            if( pConnect )
            {
                pSet = pConnect->recordset( 0 );
            }
            if( pSet )
            {
                pSet->execute_direct( "select * from cat" );
                int num = pSet->col_num();
                for( int i = 0; i < num; ++i )
                {
                    const char * lpszName = pSet->col_name( i, 0 );
                    pStrInfo->append( lpszName );
                    pStrInfo->append( "," );
                }
                LOG4( "-------------------------db column name = %s", pStrInfo->get( 0, 0 ) );
                pStrInfo->set("");
            }
            else
            {
                ret = 1;
            }
        }
        while( 0 == ret )
        {
            int nIndex = 0;
            int r = pSet->fetch();
            if( 0 != r )
            {
                break;
            }
            pSet->get( 0, nIndex );
            {
                pV->set( nIndex );
                pStrInfo->append( pV->str() );
                pStrInfo->append( "," );
            }
            pSet->get( 1, pStr );
            {
                pStrInfo->append( pStr->get(0,0) );
                pStrInfo->append( "," );
            }
            pSet->get( 2, pStr );
            {
                pStrInfo->append( pStr->get( 0, 0 ) );
                pStrInfo->append( "," );
            }
            pSet->get( 3, pStr );
            {
                pStrInfo->append( pStr->get( 0, 0 ) );
                pStrInfo->append( "," );
            }
            pSet->get( 4, pStr );
            {
                pStrInfo->append( pStr->get( 0, 0 ) );
                pStrInfo->append( "," );
            }
            LOG4( "-------------------------load db = %s", pStrInfo->get( 0, 0 ) );
            pStrInfo->set( "" );
        }
        if( pConnect )
        {
            pPool->put( pConnect );
        }
        xos_stl::release_interface( pV );
        xos_stl::release_interface( pSet );
        xos_stl::release_interface( pStrInfo );
        xos_stl::release_interface( pStr );
        return ret;
    }

    int servlet::helper_proc( http::i_task * pTask )
    {
        int ret = 0;

        xos_box::i_string * pStrTime = mgr::container()->box()->string();
        xos_box::i_string * pStrInfo = mgr::container()->box()->string();
        const char * lpszInfo = 0;

        http::i_response * pResponse = pTask->http_response();
        http::i_request * pRequest = pTask->http_request();
        xos::i_misc * pMisc = mgr::container()->misc();

        xos::i_time * pTime = mgr::container()->xos()->tm();

        {
            pTime->get_time();
            pTime->get_time_name_ymdhms( pStrTime );
            mgr::container()->crt()->sprintf( pStrInfo, "this is in servlet, simulate slow job, done block 1 second, time = %s", pStrTime->get( 0, 0 ) );
            lpszInfo = pStrInfo->get( 0, 0 );
        }
        // 生成jsession的cookie，如果没有
        {
            http::i_session * pS = pRequest->session( 0 );
            if( !pS )
            {
                http::i_cookie * pC = mgr::container()->http()->cookie();
                pC->name( xos_http_protocol::HTTP_SESSION_ID );
                {
                    char guid[100] = {0};
                    pMisc->create_guid( guid );
                    pC->value( guid );
                }
                pResponse->cookies()->push_back( pC );
                pS = mgr::container()->http()->session( pC->value(0) );
                pRequest->session( pS );
                pC = 0;
            }
        }
        {
            LOG4( "servlet info : %s", lpszInfo );
        }

        xos_stl::release_interface( pStrTime );
        xos_stl::release_interface( pStrInfo );
        xos_stl::release_interface( pTime );

        return ret;
    }

    int servlet::init_data()
    {
        int ret = 0;
        m_nStep = 0;
        return ret;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int servlet::init()
    {
        int ret = 0;
        return ret;
    }

    int servlet::term()
    {
        int ret = 0;
        init_data();
        return ret;
    }


} // xos_servlet
